﻿using System;
using System.Drawing;
using cz.zcu.PreSti.DirectX;
using cz.zcu.PreSti.XNADirectX;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using System.Windows.Forms;

namespace cz.zcu.PreSti.Components
{
    public class TextStimulus : RunnableComponent
    {
        private XNADirectXPresentation present;
        private SpriteFont UVfont;
        private string text = "Arial";
        private Microsoft.Xna.Framework.Point position = new Microsoft.Xna.Framework.Point();
        private Microsoft.Xna.Framework.Color color = Microsoft.Xna.Framework.Color.White;
        private bool fontChanged = true;
        private String font = "";
        private bool italics = false;
        private bool bold = false;
        Vector2 scaleVector = new Vector2(1, 1);
        private int fontSize = 16;
        private double rotation = 1; 
        private bool centred = false;
        private String alignmentHorizontal;
        private String alignmentVertical;



        private const String ERR_MSG = "Sound stimulus cannot work properly, because presentation object does not support audio output.";

        public const String CHOOSER_MSG = "Move chosen sound to the top...";
        public enum FontNames { Arial, TimesNewRoman, Georgia, Segoe };
        public enum ColorNames { Yellow, Orange, Red, Blue, Green, Purple, Brown };
        private GameServiceContainer services = new GameServiceContainer();
        private ContentManager contentManager;

        public TextStimulus(IPresentation p)  : base(p, 2, 1, 6, 0)
        {
            if (p is XNADirectXPresentation)
            {
                present = (XNADirectXPresentation)p;
            }

            Priority = 10;
            Finished += new EventHandler(onFinished);
        }

        public void initFont()
        {
            if (font.Equals(SoundStimulus.CHOOSER_MSG)
                || font.Trim().Equals(""))
            {
                font = FontNames.Arial.ToString();
            }

            // handling bold and italics font attrs
            if (bold)
            {
                font += "b";
            }
            if (italics)
            {
                font += "i";
            }

            services.AddService(typeof(IGraphicsDeviceService), present/*.GraphicsDeviceServiceRefference*/);
            contentManager = new ContentManager(services, "Content");
            UVfont = contentManager.Load<SpriteFont>(font);
        }

        #region parameters

        public String Text
        {
            get
            {
                return text;
            }
            set
            {
                text = value;
                if (text == null) text = "";
            }
        }

        public Microsoft.Xna.Framework.Point Position
        {
            get
            {
                return position;
            }
            set
            {
                position = value;
            }
        }

        public Microsoft.Xna.Framework.Color Color
        {
            get
            {
                return color;
            }
            set
            {
                color = value;
            }
        }

        public String FontName
        {
            get
            {
                return font;
            }
            set
            {
                font = value;
            }
        }

        public int FontSize 
        { 
            get
            { 
                return fontSize;
            } 
            set 
            { 
                fontSize=value; 
                fontChanged=true; 
            } 
        }

        public bool Italics
        {
            get
            {
                return italics;
            }
            set
            {
                italics = value;
            }
        }

        public bool Bold
        {
            get
            {
                return bold;
            }
            set
            {
                bold = value;
            }
        }

        public double Rotation
        {
            get 
            {
                return rotation; 
            }
            set 
            {
                rotation =value; 
            } 
        }

        public bool Centred
        {
            get
            {
                return centred;
            }
            set
            {
                centred = value;
            }
        }

        public String AlignmentHorizontal
        {
            get { return alignmentHorizontal; }
            set { alignmentHorizontal = value; }
        }

        public String AlignmentVertical
        {
            get { return alignmentVertical; }
            set { alignmentVertical = value; }
        }


        #endregion

        private void CountCordinates()
        {
            Vector2 size = UVfont.MeasureString(text);
            int height = present.WindowCont.Size.Height;
            int width = present.WindowCont.Size.Width;

            //Horizontal alignment
            if (alignmentHorizontal == "none")
            {
                
            }
            if (alignmentHorizontal == "left")
            {
                position.X = 0;                
            }
            if (alignmentHorizontal == "center")
            {
                position.X = (int)((width / 2) - ((size.X * scaleVector.X / 2)));
            }
            if (alignmentHorizontal == "right")
            {
                
                position.X = (int)(width - (size.X * scaleVector.X + 30));
            }
            //Vertical alignment
            if (alignmentVertical == "none")
            {

            }
            if (alignmentVertical == "top")
            {
                position.Y = 0;
            }
            if (alignmentVertical == "center")
            {
                position.Y = (int)((height / 2) - ((size.Y * scaleVector.Y / 2) + 55));
            }
            if (alignmentVertical == "bottom")
            {
                position.Y = (int)(height - (size.Y * scaleVector.Y + 55));
            }
        }


        public override void update()
        {
            if (present != null)
            {
                
                if (fontChanged)
                {
                    scaleVector = countFontSize();
                    initFont();
                    fontChanged = false;
                }
            }
        }

        public override void draw()
        {
            CountCordinates();
            Vector2 vector = new Vector2(position.X, position.Y);
            Vector2 origin = new Vector2(0, 0);
            
            float rotation = 0;

            // delay analysis
            present.startStopClock();
            present.SpriteBatch.DrawString(UVfont, text, vector, color, rotation, origin, scaleVector, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 0);
        }

        // method counting a scale vector from desired font size
        // counted from default font size
        private Vector2 countFontSize()
        {
            int defaultSize = 14;

            float scale = fontSize / (float)defaultSize;

            Vector2 scaleVector = new Vector2(scale, scale);

            return scaleVector;
        }

        private void onFinished(object sender, EventArgs e)
        {
            trigOut(0);
        }

        public override void trigIn(int n)
        {
            switch (n)
            {
                case 0:
                    base.trigIn(n);
                    break;
                case 1:
                    terminate();
                    break;
            }
        }

        public override void setValueToSetter(int setterN, object value)
        {
            base.setValueToSetter(setterN, value);
            switch (setterN)
            {
                case 1:
                    convertValue(ref text, value); break;
                case 2:
                    int x = position.X;
                    convertValue(ref x, value);
                    position.X = x;
                    break;
                case 3:
                    int y = position.Y;
                    convertValue(ref y, value);
                    position.Y = y;
                    break;
            }
        }
    }
}
